import redis
import pymongo
import time

from Perception import Perception
from Wander import Wander
from Relation import Relation
from together import Together

with open('../config.py', 'r', encoding="utf-8") as f:
    exec(f.read())


class RedisLog():
    def __init__(self, host, port, password):
        # self.log_db = redis.ConnectionPool(host="192.168.1.160", port=46379, password="12345678", db=1)
        pool1 = redis.ConnectionPool(host=host, port=port, password=password, db=1, decode_responses=True)
        pool2 = redis.ConnectionPool(host=host, port=port, password=password, db=2, decode_responses=True)
        pool5 = redis.ConnectionPool(host=host, port=port, password=password, db=5, decode_responses=True)
        pool15 = redis.ConnectionPool(host=host, port=port, password=password, db=15, decode_responses=True)
        self.log_db = redis.Redis(connection_pool=pool1)
        self.acvs_acvs_db = redis.Redis(connection_pool=pool2)
        self.acvs_face_db = redis.Redis(connection_pool=pool5)
        self.face_db = redis.Redis(connection_pool=pool15)

    def pop_log(self, log_name):
        return self.log_db.rpop(log_name)

    def get_face(self, id):
        return self.face_db.hgetall(name=id)

    def ping(self):
        return self.log_db.ping()

    def get_acvs_acvs(self, acvs_id):
        return self.acvs_acvs_db.zrange(acvs_id, 0, -1, withscores=False)

    def get_acvs_face_count(self, acvs_id):
        return self.acvs_face_db.zcard(acvs_id)
        # return self.acvs_face_db.zcount(acvs_id, 0, 200000)


class MyMongoClient():
    def __init__(self, host, port):
        while 1:
            try:
                client = pymongo.MongoClient(host=host, port=port)
                self.address = client.address
                self.backup = client.guidang4.log_backup
                self.relation = client.guidang4.log_relation
                self.wander = client.guidang4.log_wander
                self.statistics = client.guidang4.log_relation_count
                self.together = client.guidang4.together
                self.perception = client.guidang4.perception
                break
            except Exception as e:
                print("Get Mongo failed:", e)
                time.sleep(2)

    def ins_one_backup(self, data):
        self.backup.insert_one(data)

    def ins_one_relation(self, data):
        self.relation.insert_one(data)

    def update_relation(self, data):
        acvs_id = data.get("acvs_id")
        tail_acvs_id = data.get("tail_acvs_id")
        score = data.get("score")
        self.statistics.update_one(filter={"acvs_id": acvs_id, "tail_acvs_id": tail_acvs_id},
                                   update={"$inc": {"score": score}},
                                   upsert=True)

    # 只读取1分钟之前开始的doc
    def load_from_backup(self, timestamp):
        return list(self.backup.find({"timestamp": {"$gt": timestamp - 60}}))

    def ins_one_wander(self, data):
        self.wander.insert_one(data)

    def ins_together(self, data):
        # self.together.insert_one(data)
        self.relation.insert_one(data)

    def up_perception(self, data):
        name = "%s_%s" % (data.get("acvs_id"), data.get("day"))
        img = self.perception.find_one({"_id": name})
        if not img:
            data.update({"_id": name, "count": 1})
            self.perception.insert_one(data)
        else:
            self.perception.update_one({"_id": name}, {"$inc": {"count": 1}}, upsert=True)
            self.perception.update_one({"_id": name}, {"$set": {"p": data.get("p")}}, upsert=True)


def main():
    log_name = "logZZQ"
    # log_name = "logJHT"
    meet_time = relationinfo['meet_time']
    time_interval = relationinfo['time_interval']
    wander_count = relationinfo['wander_count']
    reset_time = relationinfo['reset_time']
    wander_reset_time = relationinfo['wander_reset_time']
    together_time = relationinfo['together_time']
    together_people_count = relationinfo['together_people_count']
    db_log = RedisLog(host=redisinfo['ip'], port=redisinfo['port'], password=redisinfo['password'])
    # db_log = RedisLog(host="192.168.1.48", port=6379, password="12345678")
    mongo_client = MyMongoClient(host=mongoinfo['ip'], port=mongoinfo['port'])

    # log_name = "logSHS"
    # # 同行,相遇间隔
    # meet_time = 5
    # # 徘徊,时间间隔
    # time_interval = 5
    # # 徘徊,次数
    # wander_count = 5
    # # 同行,清空时间
    # reset_time = 300
    # # 徘徊,清空时间
    # wander_reset_time = 3000
    # db_log = RedisLog(host="192.168.1.160", port=46379, password="12345678")
    # mongo_client = MyMongoClient(host="192.168.1.42", port=27017)

    # init
    relation = Relation(mongo_client=mongo_client, meet_time=meet_time, time_interval=time_interval,
                        reset_time=reset_time)
    wander = Wander(mongo_client=mongo_client, time_interval=time_interval, wander_count=wander_count,
                    reset_time=wander_reset_time)
    together_client = Together(mongo_client=mongo_client, redis_client=db_log, together_time=together_time,
                               together_people_count=together_people_count)
    perception = Perception(mongo_client=mongo_client, redis_client=db_log)

    while True:
        try:
            db_log.ping()
        except Exception as e:
            print("Get Redis Failed:", e)
            time.sleep(5)
            continue
        try:
            act = db_log.pop_log(log_name).split("&")
        except AttributeError:
            print("Query empty...")
            time.sleep(3)
            continue
        try:
            # action = act[0].split("&")
            # acvs_id = act[1]
            if act[0] != "InsAcvs":
                continue
            print("Run4ing...")
            action = act[1].split(">")
            face_id = action[0]
            acvs_id = action[1]
            face = db_log.get_face(face_id)
            camera_id = face.get("camera_id")
            timestamp = int(face.get("timestamp"))
            cap_data = {"face_id": face_id, "camera_id": camera_id, "timestamp": int(timestamp), "acvs_id": acvs_id}
            face_uri = face.get("face_image_uri")
            picture_uri = face.get("picture_uri")
            # relation logic
            relation.handel_logic(camera_id, timestamp, acvs_id)
            # wander logic
            wander.handel_logic(camera_id, timestamp, acvs_id, face_uri, picture_uri)
            # together logic
            together_client.handel_logic(camera_id, timestamp, acvs_id, face_id)
            # perception logic
            perception.handel_logic(timestamp, acvs_id, face_id)

            # 插入备份
            mongo_client.ins_one_backup(cap_data)
            # print("insert backup success")
        except Exception as e:
            print("Action Failed", e)
            continue


if __name__ == '__main__':
    main()
